
--Files
include( 'weap.lua' )

function AddDir(dir)
    print(dir)
	dir = tostring(dir)
    for k,v in pairs(file.Find(dir.."/*","GAME")) do
	    print(dir.."/"..v)
        resource.AddFile(dir.."/"..v,"GAME")
    end
end
resource.AddFile("sound/hw/winv2.wav")
resource.AddFile("sound/hw/lose.wav")
--[[AddDir("materials/models/weapons/v_models/tehsnakesmg")
AddDir("materials/models/weapons/w_models/tehsnakesmg")
AddDir("materials/models/shellz")
resource.AddFile("materials/models/shells/9mm/shell_9mm.vmt")
resource.AddFile("materials/models/shells/57/shell_57.vmt")
resource.AddFile("materials/models/shells/556/shell_556.vmt")
resource.AddFile("materials/models/shells/762nato/shell_762nato.vmt")
AddDir("materials/trails")
AddDir("materials/vgui/entities")
AddDir("materials/vgui/gfx/vgui")
AddDir("materials/vgui/hud")
resource.AddFile("models/items/sniper_round_box.mdl")
resource.AddFile("models/weapons/v_smg_pop.mdl")
resource.AddFile("models/weapons/w_smg_pop.mdl")
resource.AddFile("models/shells/shell_9mm.mdl")
resource.AddFile("models/shells/shell_12gauge.mdl")
resource.AddFile("models/shells/shell_57.mdl")
resource.AddFile("models/shells/shell_556.mdl")
resource.AddFile("models/shells/shell_762nato.mdl")
AddDir("sound/weapons/p90")
--]]
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile("cl_scoreboard.lua")
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_hud.lua" )
include( 'shared.lua' )

local currentWave = 0
local nextteam = 1

local team1LastNotice = 0
local team2LastNotice = 0
local team1WarningLevel = 5 --  Warning levels will facilitate giving players special warnings when base is at 75%, 50%, 25%, 10% and 5%
local team2WarningLevel = 5

function GM:PlayerShouldTakeDamage( victim, pl )
	--if pl:IsPlayer() and currentWave != 0 then -- check the attacker is player 	
	--	return false -- do not damage the player
	--else
		return true
	--end
end


waveMap = {}

waveMap[1] = {
	t1 = 20,
	t2 = 5,
	t3 = 0,
	t4 = 0
}
waveMap[2] = {
	t1 = 23,
	t2 = 10,
	t3 = 1,
	t4 = 0
}
waveMap[3] = {
	t1 = 20,
	t2 = 15,
	t3 = 3,
	t4 = 1
}
waveMap[4] = {
	t1 = 25,
	t2 = 15,
	t3 = 3,
	t4 = 3
}
waveMap[5] = {
	t1 = 15,
	t2 = 0;
	t3 = 0,
	t4 = 9
}
waveMap[6] = {
	t1 = 15,
	t2 = 5;
	t3 = 5,
	t4 = 5
}
waveMap[7] = {
	t1 = 40,
	t2 = 0;
	t3 = 0,
	t4 = 0
}
waveMap[8] = {
	t1 = 0,
	t2 = 30;
	t3 = 0,
	t4 = 4
}
waveMap[9] = {
	t1 = 35,
	t2 = 15;
	t3 = 12,
	t4 = 8
}
waveMap[10] = {
	t1 = 50,
	t2 = 65;
	t3 = 46,
	t4 = 9
}


NPCTier1 = {}
NPCTier2 = {}
NPCTier3 = {}
NPCTier4 = {}


NPCTier1[1] = {
	name = "headCrab",
	model = "npc_headcrab",
	carryWeapon = false,
	pointValue = 1,
	moneyValue = 2,
	beginHealth = 5,
	hp = 5
}
NPCTier1[2] = {
	name = "zombie",
	model = "npc_zombie",
	carryWeapon = false,
	pointValue = 1,
	moneyValue = 10,
	hp = 15
}
NPCTier1[3] = {
	name = "antLion",
	model = "npc_antlion",
	carryWeapon = false,
	pointValue = "1",
	moneyValue = 7,
	hp = 20
}
NPCTier1[4] = {
	name = "zombieTorso",
	model = "npc_zombie_torso",
	carryWeapon = false,
	pointValue = "1",
	moneyValue = 7,
	hp = 35
}
NPCTier1[5] = {
	name = "metroPolice",
	model = "npc_metropolice",
	carryWeapon = true,
	pointValue = "1",
	moneyValue = 15,
	hp = 35
}
NPCTier1[6] = {
	name = "manhack",
	model = "npc_manhack",
	carryWeapon = false,
	pointValue = "1",
	moneyValue = 1,
	hp = 10
}	


NPCTier2[1] = {
			name = "fastHeadcrab",
			model = "npc_headcrab_fast",
			carryWeapon = false,
			pointValue = "2",
			moneyValue = 10,
			hp = 30
		}
NPCTier2[2] = {
			name = "fastZombie",
			model = "npc_fastzombie",
			carryWeapon = false,
			pointValue = "2",
			moneyValue = 8,
			hp = 35
		}
NPCTier2[3] = {
			name = "fastZombieTorso",
			model = "npc_zombie_torso",
			carryWeapon = false,
			pointValue = "2",
			moneyValue = 4,
			hp = 90
		}
NPCTier2[4] = {
			name = "combineSoldier",
			model = "npc_combine_s",
			carryWeapon = true,
			pointValue = "2",
			moneyValue = 10,
			hp = 100
		}
NPCTier3[1] = {
			name = "combineSoldier",
			model = "npc_combine_s",
			carryWeapon = true,
			pointValue = "3",
			moneyValue = 50,
			hp = 200
}
NPCTier4[1] = {
			name = "Stalker",
			model = "npc_stalker",
			carryWeapon = false,
			pointValue = "4",
			moneyValue = 10,
			hp = 150
}



function SpawnAi(Npc)
	local ai1 = ents.Create(Npc.model)
	local ai2 = ents.Create(Npc.model)
	ai1:SetPos(Vector(math.random(-100,350),math.random(-100,350),40))
	ai2:SetPos(Vector(math.random(4208,4500),math.random(-100,350),40))
	ai1:Spawn()
	ai2:Spawn()
	ai1:SetColor(255, 0, 0, 255) 
	ai1:SetHealth(Npc.hp)
	ai2:SetHealth(Npc.hp)
	if Npc.carryWeapon == true then
	    ai1:Give( "weapon_zm_mac10" )
		--ai1:Give( "item_ammo_smg1" )
		ai2:Give( "weapon_zm_mac10" )
		--ai2:Give( "item_ammo_smg1" )
	end
	for k,v in pairs(player.GetAll()) do
		if v:Team() == 1 then
			ai2:AddEntityRelationship(v,D_HT,99)
			ai1:AddEntityRelationship(v,D_LI,99)
		else
			ai1:AddEntityRelationship(v,D_HT,99)
			ai2:AddEntityRelationship(v,D_LI,99)
		end
	end
	ai1:SetNWInt("aiTeam", 1)
	ai2:SetNWInt("aiTeam", 2)

	--ai1:SetNWInt("moneyVal", npc.pointValue)
	--ai2:SetNWInt("moneyVal", npc.pointValue)
	--ai1:SetNWInt("moneyVal", npc.moneyValue)
	--ai2:SetNWInt("moneyVal", npc.moneyValue)
end


function SetRelationships() 
print("called relationships")
	local npcs = ents.FindByClass("npc_*")
	for k, ent in pairs(npcs) do
		local aiTeam = ent:GetNWInt("aiTeam")
		local ships = ents.FindByClass("npc_*")
		for v, shp in pairs(ships) do
			shpTeam = shp:GetNWInt("aiTeam")
			if aiTeam == shpTeam then
				ent:AddEntityRelationship(shp,D_LI,99)
			else
				ent:AddEntityRelationship(shp,D_HT,99)
			end
		end
	end
end




function beginWave()

	local RandomSpawn = false
	timer.Destroy("WaveDelay")
	currentWave = currentWave + 1
	umsg.Start( "WaveChange" )
	umsg.Long(currentWave)
	umsg.End()
	for k,v in pairs(player.GetAll()) do
		v:SetNWInt("currentWave", currentWave)
	end
	if currentWave == 1 then
		SendMsg("GAME IS STARTING!")
		removeshit()
		gamesetup()
		for k,v in pairs(player.GetAll()) do
			v:ConCommand("playaudio 2")
		end
	end
	PrintMessage( HUD_PRINTTALK, "Wave ".. currentWave .."..starting!" )
	local currentWaveMap = waveMap[waveNum]	
	
	if RandomSpawn then
	
		for x=1, waveMap[currentWave].t1 do		
			SpawnAi(GetRandomNPCFromTier(1))
		end	
		
		for x=1, waveMap[currentWave].t2 do
			SpawnAi(GetRandomNPCFromTier(2))
		end	
		
		for x=1, waveMap[currentWave].t3 do
			SpawnAi(GetRandomNPCFromTier(3))
		end	
		
		for x=1, waveMap[currentWave].t4 do
			SpawnAi(GetRandomNPCFromTier(4))
		end	
		
	else
		local rNPC1 = GetRandomNPCFromTier(1)
		local rNPC2 = GetRandomNPCFromTier(2)
		local rNPC3 = GetRandomNPCFromTier(3)
		local rNPC4 = GetRandomNPCFromTier(4)
		
		for x=1, waveMap[currentWave].t1 do		
			SpawnAi(rNPC1)
		end	
		SetRelationships() 
		for x=1, waveMap[currentWave].t2 do
			SpawnAi(rNPC2)
		end	
		SetRelationships() 
		for x=1, waveMap[currentWave].t3 do
			SpawnAi(rNPC3)
		end	
		SetRelationships() 
		for x=1, waveMap[currentWave].t4 do
			SpawnAi(rNPC4)
		end			
	     
	end	
	SetRelationships() 
	
end

function GetRandomNPCFromTier(spawnFromTier)
	local tierSize = 0
	
	if spawnFromTier == 1 then
		tierSize = table.Count(NPCTier1)
	elseif spawnFromTier == 2 then
		tierSize = table.Count(NPCTier2)
	elseif spawnFromTier == 3 then
		tierSize = table.Count(NPCTier3)
	elseif spawnFromTier == 4 then
		tierSize = table.Count(NPCTier4)
	end
	
	local npcLocation = math.random(1,tierSize)
	
	if spawnFromTier == 1 then
		return NPCTier1[npcLocation]
	elseif spawnFromTier == 2 then
		return NPCTier2[npcLocation]
	elseif spawnFromTier == 3 then
		return NPCTier3[npcLocation]
	elseif spawnFromTier == 4 then
		return NPCTier4[npcLocation]
	end	
end


function GetNpcs ()
local Npcs 

end

ALLOW_LAAI = true



function GM:PlayerInitialSpawn( ply )
if nextteam == 1 then 
    ply:SetTeam( 1 )
	nextteam = 2
	elseif nextteam == 2 then
	 ply:SetTeam( 2 )
	nexteam = 1
	end
end

function GiveGuns(ply)
	ply:Give("weapon_crossbow")
	ply:GiveAmmo(200,"XBowBolt")
end

--Spawn in the bases that we will be defending 
function gamesetup()
	local base1=ents.Create("npc_antlionguard")
	--base1:SetModel("models/props_c17/oildrum001.mdl")
	base1:SetPos(Vector(-800,0,20))
	base1:SetHealth(300)
	base1:SetNWInt("aiTeam", 1)
	base1:SetColor(255, 0, 0, 255) 
	base1:Spawn()
	local base2=ents.Create("npc_antlionguard")
	--base2:SetModel("models/props_c17/oildrum001.mdl")
	base2:SetPos(Vector(5408,326,20))
	base2:SetHealth(300)
	base2:SetNWInt("aiTeam", 2)
	--base2:SetColor(0, 255, 0, 255) 
	base2:Spawn()
	for k,v in pairs(player.GetAll()) do
			base1:AddEntityRelationship(v,D_LI,99)
			base2:AddEntityRelationship(v,D_LI,99)
	end
end

--Let's get the players set up with some guns! bang bang
function GM:PlayerLoadout( ply )
	
	ply:SetWalkSpeed( 400 )

    if ply:Team() == 1 then
        ply:Give( "weapon_zm_mac10" )
		ply:GiveAmmo( 999, "smg1" )
		ply:GiveAmmo( 2, "AR2AltFire" )
		ply:SetModel("models/player/combine_soldier.mdl")
	elseif ply:Team() == 2 then
        ply:Give( "weapon_zm_mac10" )
		ply:GiveAmmo( 999, "smg1" )
		ply:GiveAmmo( 2, "AR2AltFire" )
        ply:SetModel( "models/player/combine_soldier.mdl" )
    end
end
function GM:PlayerSpawn( ply )
ply:SetModel("models/player/combine_soldier.mdl")
   if ply:Team() == 1 then
        ply:Give( "weapon_zm_mac10" )
		ply:GiveAmmo( 999, "smg1" )
		ply:GiveAmmo( 2, "AR2AltFire" )
		ply:SetModel("models/player/combine_soldier.mdl")
	elseif ply:Team() == 2 then
        ply:Give( "weapon_zm_mac10" )
		ply:GiveAmmo( 999, "smg1" )
		ply:GiveAmmo( 2, "AR2AltFire" )
        ply:SetModel( "models/player/combine_soldier.mdl" )
    end
 local oldhands = ply:GetHands()
  if ( IsValid( oldhands ) ) then oldhands:Remove() end

  local hands = ents.Create( "gmod_hands" )
  if ( IsValid( hands ) ) then
    ply:SetHands( hands )
    hands:SetOwner( ply )

    -- Which hands should we use?
    local cl_playermodel = ply:GetInfo( "cl_playermodel" )
    local info = player_manager.TranslatePlayerHands( cl_playermodel )
    if ( info ) then
      hands:SetModel( info.model )
      hands:SetSkin( info.skin )
      hands:SetBodyGroups( info.body )
    end

    -- Attach them to the viewmodel
    local vm = ply:GetViewModel( 0 )
    hands:AttachToViewmodel( vm )

    vm:DeleteOnRemove( hands )
    ply:DeleteOnRemove( hands )

    hands:Spawn()
  end
end

function team_1( ply )
    ply:SetTeam( 1 )
end

function team_2( ply )
    ply:SetTeam( 2 )
end

--This shit will that the game and run waves


--cleans the map
function removeshit()
	local removes = ents.FindByClass("prop_physics")
	for k, ent in pairs(removes) do
		ent:Remove()
	end
	local removes = ents.FindByClass("npc_*")
	for k, ent in pairs(removes) do
		ent:Remove()
	end
	local removes = ents.FindByClass("npc_antlionguard")
	for k, ent in pairs(removes) do
		ent:Remove()
	end	
end
function SendMsg(text)
	umsg.Start( "GameMsg" )
	umsg.String(text)
	umsg.End()
end

--keep track of kills and shit
function GM:OnNPCKilled( ent, ply, weapon )
    if ply:IsPlayer() then
		ply:ConCommand("play HL1/fvox/bell.wav")
	end
	local ants = ents.FindByClass("npc_*")
	local totalants = table.Count( ants )
	
	print("Total ants: ".. totalants)
	
	if totalants < 4 then
		SendMsg("Wave over!")
		SendMsg("Next wave starts in 0:10")
		
		--PrintMessage( HUD_PRINTTALK, "Wave over!")
		--PrintMessage( HUD_PRINTTALK, "Next wave starts in 0:10")
		timer.Create("WaveDelay",10,0,beginWave)
		--timer.Create( "delaydisshit1", 1, 5+currentWave, spawnai1 )
	end
    --print("da crap")
	if ent:GetClass() == "npc_antlionguard" then
	local aiteam = ent:GetNWInt("aiteam")
		GameWin(aiteam)
		--print("We won!?")
	end
	
	
	if not ply:IsNPC() then
		local aiteam = ent:GetNWInt("aiteam")
		if ply:Team() != aiteam then
			ply:AddFrags(1)			
		else
			ply:AddFrags(-1)
			ply:PrintMessage( HUD_PRINTTALK, "Killed Team Minion!!" )
		end
	end
	ent:Remove()
end
-- Set the maximum time in seconds before a player must respawn
local maxdeathtime = 10;
 
-- Create a hook for the GM:PlayerDeath() function that
-- sets our two variables when the player dies
function player_initdeath( ply, wep, killer )
 
     ply.nextspawn = CurTime() + maxdeathtime; -- set when we want to spawn
 
end
hook.Add( "PlayerDeath", "player_initalize_dvars", player_initdeath );
 
function playerforcerespawn( ply )
	if ply.nextspawn then
     if (CurTime()>=ply.nextspawn) then
          ply:Spawn()
          ply.nextspawn = math.huge
     else
	 return false
	 end
	 end
end
 
hook.Add( "PlayerDeathThink", "player_step_forcespawn", playerforcerespawn );

function GameWin(tea)
	for k,v in pairs(player.GetAll()) do
		print(v:Team())
		print(tea)
		print("--")
		if v:Team() != tea then
		v:ConCommand("playaudio 4")
		v:PrintMessage( HUD_PRINTTALK, "WIN!!!!" )
		else
		v:ConCommand("playaudio 5")
		v:PrintMessage( HUD_PRINTTALK, "LOSE =(" )
		end
	end
	SendMsg("GAME OVER! Team ".. team.GetName( tea ) .." LOSES!")
	--PrintMessage( HUD_PRINTTALK, "GAME OVER! Team ".. team.GetName( tea ) .." LOSES!")
	removeshit()
	timer.Destroy("WaveDelay")
	currentWave = 0
end
function GM:ScaleNPCDamage( npc, hitgroup, dmginfo )
if ( npc:GetClass( ) == "npc_antlionguard" ) then
	if dmginfo:GetAttacker():IsPlayer() then
			dmginfo:SetDamage(0)
			dmginfo:SetMaxDamage(0)
	end
	end
end
function GM:EntityTakeDamage( ent, dmginfo )

	if ( ent:GetClass( ) == "npc_antlionguard" ) then

		
		local aiteam = ent:GetNWInt("aiteam")
		local hp = ent:Health( )
		local maxHP = ent:GetMaxHealth()
		
		if ent:IsValid() and ent:Health( ) and ent:GetNWInt("aiteam") then
			PrintHealthWarning(ReturnPercentHealthLeft(hp, maxHP), aiteam)		
		end
	end
end

function PrintHealthWarning(percentLeft, teamNum)

	--print("teamNum: ".. teamNum .." & percentLeft = ".. percentLeft .."Team Warning: ".. GetTeamWarningLevel(teamNum))

	if percentLeft then  -- make sure percentLeft is not == nil
		if percentLeft > 70 and percentLeft < 75 and GetTeamWarningLevel(teamNum) > 4 then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("TEAM " .. teamNum .. " YOUR BASE IS UNDER ATTACK!! Your base is at 75% health!" )
			AdjTeamWarningLevel(teamNum)
		elseif percentLeft > 50 and percentLeft < 55 and GetTeamWarningLevel(teamNum) > 3 then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("TEAM " .. teamNum .. " YOUR BASE IS UNDER ATTACK!! Your base is at 50% health!" )
			AdjTeamWarningLevel(teamNum)
		elseif percentLeft > 20 and percentLeft < 25 and GetTeamWarningLevel(teamNum) > 2 then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("TEAM " .. teamNum .. " YOUR BASE IS UNDER ATTACK!! Your base is at 25% health!" )
			AdjTeamWarningLevel(teamNum)
		elseif percentLeft > 10 and percentLeft < 15 and GetTeamWarningLevel(teamNum) > 1 then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("TEAM " .. teamNum .. " YOUR BASE IS UNDER ATTACK!! Your base is at 15% health!" )
			AdjTeamWarningLevel(teamNum)
		elseif percentLeft > 0 and percentLeft < 5 and GetTeamWarningLevel(teamNum) > 0 then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("TEAM " .. teamNum .. " YOUR BASE IS UNDER ATTACK!! Your base is at 5% health!" )
			AdjTeamWarningLevel(teamNum)
		elseif teamNum == 1 and team1LastNotice < CurTime() then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("Status Update: Team 1 base at " .. percentLeft .. "% health!" )
			team1LastNotice = CurTime() + 25
		elseif teamNum == 2 and team2LastNotice < CurTime() then
			for k,v in pairs(player.GetAll()) do
				v:ConCommand("playaudio 1")
			end
			SendMsg("Status Update: Team 2 base at " .. percentLeft .. "% health!" )
			team2LastNotice = CurTime() + 25
		end	
	end
	
	
end

function ReturnPercentHealthLeft(currentHealth, maxHealth)
	return (currentHealth / maxHealth) * 100
end

function GetTeamWarningLevel(teamNum)	
	if teamNum == 1 then
		return team1WarningLevel
	elseif teamNum == 2 then
		return team2WarningLevel
	end
end

function AdjTeamWarningLevel(teamNum)
	if teamNum == 1 then
		team1WarningLevel = team1WarningLevel - 1
	else
		team2WarningLevel = team2WarningLevel - 1
	end
end


function EyeTrace(user)
	trd = {}
	trd.start = user:GetShootPos()
	trd.endpos = trd.start + (user:GetAimVector() * 10000)
	trd.filter = user
	return util.TraceLine(trd)
end
concommand.Add( "team_1", team_1 )
concommand.Add( "team_2", team_2 )
concommand.Add("startwave", beginWave )

concommand.Add("guns!", GiveGuns)

function LAAI_Think()

	if ALLOW_LAAI then     -- lets us turn on and off AI Thinking
	
		local npcs = ents.FindByClass("npc_*") -- Collection of all the Ants in the Game
		
		for k, ent in pairs(npcs) do
		if ent:GetClass() == "npc_antlionguard" then
		ent:SetSchedule(1)
		end
		if ent:GetClass() != "npc_antlionguard" then
			if ent.AIUpdate == nil then  -- initializes the AIUpdate integer which stores the NEXT time it needs to think
				ent.AIUpdate = 0
			end
		
			if ent:GetEnemy() == nil then 			
				if CurTime() > ent.AIUpdate then
					local aiteam = ent:GetNWInt("aiTeam")
					--print("aiteam set "..aiteam)
					if aiteam == 1 then 
						ent.AIUpdate = CurTime()+ 4 -- We'll only update every few seconds; otherwise these buggers would never move. :3
						ent:SetLastPosition(Vector(5102,205,60))
						ent:SetSchedule(72)			
						--print("update team1")
					elseif aiteam == 2 then
						ent.AIUpdate = CurTime()+ 4 -- We'll only update every few seconds; otherwise these buggers would never move. :3
						ent:SetLastPosition(Vector(0,0,60))
						ent:SetSchedule(72)
						--print("update team2")					
					else
						if ent:IsValid() then
							--ent:remove()
						end
					end
				end	
						--print("doing this")
			end
		end
		end
	end
end

hook.Add("Think","LAAI",LAAI_Think)


